#include "./BSP/KEY/key_manager.h"
#include "./BSP/LED/led_manager.h"
#include "./BSP/LCD/lcd_init.h"
#include "./sys_param/sys_param.h"
#include "./BSP/BEEP/beep_alert_manager.h"
#include "./BSP/BEEP/beep_music_manager.h"
#include "stdio.h"

/* -------------------------------------------- 按键IO初始化 ---------------------------------------------- */

static void InitKeyIo(void)
{ 
    GPIO_InitTypeDef gpio_init_struct;
    
    /* 开启时钟 */
    KEY0_GPIO_CLK_ENABLE();                                     /* KEY0时钟使能 */
    KEY1_GPIO_CLK_ENABLE();                                     /* KEY1时钟使能 */
    KEY2_GPIO_CLK_ENABLE();                                     /* KEY2时钟使能 */

    /* GPIO初始化 */
    gpio_init_struct.Pin = KEY0_GPIO_PIN;                       /* KEY0引脚 */
    gpio_init_struct.Mode = GPIO_MODE_INPUT;                    /* 输入 */
    gpio_init_struct.Pull = GPIO_PULLUP;                        /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;              /* 高速 */
    HAL_GPIO_Init(KEY0_GPIO_PORT, &gpio_init_struct);           /* KEY0引脚模式设置,上拉输入 */

    gpio_init_struct.Pin = KEY1_GPIO_PIN;                       /* KEY1引脚 */
    gpio_init_struct.Mode = GPIO_MODE_INPUT;                    /* 输入 */
    gpio_init_struct.Pull = GPIO_PULLUP;                        /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;              /* 高速 */
    HAL_GPIO_Init(KEY1_GPIO_PORT, &gpio_init_struct);           /* KEY1引脚模式设置,上拉输入 */

    gpio_init_struct.Pin = KEY2_GPIO_PIN;                       /* KEY2引脚 */
    gpio_init_struct.Mode = GPIO_MODE_INPUT;                    /* 输入 */
    gpio_init_struct.Pull = GPIO_PULLUP;                        /* 上拉 */
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;              /* 高速 */
    HAL_GPIO_Init(KEY2_GPIO_PORT, &gpio_init_struct);           /* KEY2引脚模式设置,上拉输入 */
}

/* -------------------------------------------- 按键状态读取函数 ------------------------------------------- */

cotKeyState_e ReadKey0(void)
{
    /* 使用参数中保存的方向值而不是当前LCD方向 */
    uint8_t lcd_direction = g_tDisplayParam.direction;
    
    /* 在180度和90度方向时，上下按键逻辑反转 */
    if (lcd_direction == 1 || lcd_direction == 2) 
    {
        /* 屏幕旋转180度或90度时，上键的物理按键读取下键的状态 */
        return (GPIO_GetKEY() == KEY_CODE_1) ? COT_KEY_ON : COT_KEY_OFF;
    } 
    else 
    {
        /* 0度或270度方向，上键读取上键的状态 */
        return (GPIO_GetKEY() == KEY_CODE_0) ? COT_KEY_ON : COT_KEY_OFF;
    }
}

cotKeyState_e ReadKey1(void)
{
    /* 使用参数中保存的方向值而不是当前LCD方向 */
    uint8_t lcd_direction = g_tDisplayParam.direction;
    
    /* 在180度和90度方向时，上下按键逻辑反转 */
    if (lcd_direction == 1 || lcd_direction == 2) 
    {
        /* 屏幕旋转180度或90度时，上键的物理按键读取下键的状态 */
        return (GPIO_GetKEY() == KEY_CODE_0) ? COT_KEY_ON : COT_KEY_OFF;
    } 
    else 
    {
        /* 0度或270度方向，上键读取上键的状态 */
        return (GPIO_GetKEY() == KEY_CODE_1) ? COT_KEY_ON : COT_KEY_OFF;
    }
}

cotKeyState_e ReadKey2(void)
{
    return (GPIO_GetKEY() == KEY_CODE_2) ? COT_KEY_ON : COT_KEY_OFF;
}

/* -------------------------------------------- 按键回调函数 ---------------------------------------------- */

/* KEY0键回调函数 */
static void OnKey0Press(cotKey_t key)
{ 
    if (!cotKey_IsLongPress(key))  /* 判断是否触发了长按 */
    {
        if (cotKey_IsTriggerWayMet(key, COT_KEY_TRIGGER_WAY_PRESS)) /* 按下首次触发 */
        {
            printf("KEY0 pressed\r\n");
        }

        if (cotKey_IsTriggerWayMet(key, COT_KEY_TRIGGER_WAY_LOSSEN)) /* 识别到短按 */
        {
            cotLed_Toggle(LED_0);
            printf("KEY0 released\r\n");
        }
    }
    else
    {
        if (cotKey_IsTriggerWayMet(key, COT_KEY_TRIGGER_WAY_PRESS)) /* 识别到长按 */
        {
            cotLed_Toggle(LED_0);
            printf("KEY0 long press detected\r\n");
        }

        if (cotKey_IsTriggerWayMet(key, COT_KEY_TRIGGER_WAY_LOSSEN)) /* 长按松开 */
        {
            printf("KEY0 long press released\r\n");  
        }
    }
}

/* KEY1键回调函数 */
static void OnKey1Press(cotKey_t key)
{
    if (!cotKey_IsLongPress(key))  /* 判断是否触发了长按 */
    {
        if (cotKey_IsTriggerWayMet(key, COT_KEY_TRIGGER_WAY_PRESS)) /* 按下首次触发 */
        {
            printf("Key1 pressed\r\n");
        }

        if (cotKey_IsTriggerWayMet(key, COT_KEY_TRIGGER_WAY_LOSSEN)) /* 识别到短按 */
        {
            cotLed_Toggle(LED_2);
            printf("Key1 released\r\n");
        }
    }
    else
    {
        if (cotKey_IsTriggerWayMet(key, COT_KEY_TRIGGER_WAY_PRESS)) /* 识别到长按 */
        {
            cotLed_Toggle(LED_2);
            printf("Key1 long press detected\r\n");            
        }

        if (cotKey_IsTriggerWayMet(key, COT_KEY_TRIGGER_WAY_LOSSEN)) /* 长按松开 */
        {
            printf("Key1 long press released\r\n");
        }
    }
}

/* KEY2键回调函数 */
static void OnKey2Press(cotKey_t key)
{
    uint8_t clickCount = cotKey_GetClickCount(key);
    switch (clickCount)
    {
        case 1:  /* 单击 */
            cotLed_Toggle(LED_1);
            //ALERT_BeepWithCount(2000, 200, 1);  /* 2kHz，200ms，响1次 */
            MUSIC_PlayHappyBirthday(MUSIC_PLAYER_0, 70);/* 播放生日快乐歌 */
            printf("Key2 single click\r\n");
            break;
        case 2:  /* 双击 */
            cotLed_TwinkleWithCount(LED_1, 200, 2, COT_LED_OFF);
            //ALERT_BeepWithCount(2500, 150, 2);  /* 2.5kHz，150ms，响2次 */
            MUSIC_PlayWindRise(MUSIC_PLAYER_0, 70); /* 播放起风了 */
            printf("Key2 double click\r\n");
            break;
        case 3:  /* 三击 */
            cotLed_TwinkleWithCount(LED_1, 200, 3, COT_LED_OFF);
            ALERT_BeepWithCount(3000, 100, 3);  /* 3kHz，100ms，响3次 */
            printf("Key2 triple click\r\n");
            break;
        case 4:  /* 四击 */
            cotLed_TwinkleWithCount(LED_1, 200, 4, COT_LED_OFF);
            ALERT_BeepWithCount(3500, 80, 4);   /* 3.5kHz，80ms，响4次 */
            printf("Key2 quadruple click\r\n");
            break;
        default:
            if (clickCount > 4)
            {
                cotLed_TwinkleWithCount(LED_1, 200, clickCount, COT_LED_OFF);
                ALERT_BeepWithCount(4000, 60, clickCount);  /* 4kHz，60ms，响clickCount次 */
                printf("Key2 clicked %d times\r\n", clickCount);
            }
            break;
    }
}

/* -------------------------------------------- 按键初始化函数 -------------------------------------------- */

/**
 * @brief  按键初始化函数
 * @param  无
 * @retval 无
 */
void FML_KEY_Init(void)
{
    static cotKeyCfg_t s_keyTable[KEY_MAX_NUM] =
    {
        {.pfnKeyState = ReadKey0},
        {.pfnKeyState = ReadKey1},
        {.pfnKeyState = ReadKey2},
    };

    /* 初始化按键IO */
    InitKeyIo();

    /* 初始化COT按键模块 */
    cotKey_Init(s_keyTable, KEY_MAX_NUM);

    /* 注册按键回调 */
    cotKey_Listen(KEY0, OnKey0Press);
    cotKey_Listen(KEY1, OnKey1Press);
    cotKey_Listen(KEY2, OnKey2Press);

    /* 配置按键模式 */
    cotKey_ConfigLongPressMode(KEY0, 1500, 500);    /* KEY0配置为长按模式，1500ms长按，500ms重复触发 */
    cotKey_ConfigLongPressMode(KEY1, 1500, 500);    /* KEY1配置为长按模式，1500ms长按，500ms重复触发 */
    cotKey_ConfigClickMode(KEY2, 200);              /* KEY2配置为连击模式，200ms连击间隔 */
}
